package com.bee.shepherd.common.filter;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.*;
import com.qunar.finance.nbdata.adapter.api.been.RequestParam;
import com.qunar.flight.qmonitor.QMonitor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

@Activate(group = {Constants.PROVIDER, Constants.CONSUMER})
public class RpcMonitorFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(RpcMonitorFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        long start = System.currentTimeMillis();
        RpcContext context = RpcContext.getContext();
        String key="";
        String simpleName = invoker.getInterface().getSimpleName();
        if (context.isConsumerSide()) {
            key = "RPC_" + simpleName + "_" + invocation.getMethodName() + "_Consumer";
            QMonitor.recordOne("RPC_Consumer_total");
            QMonitor.recordOne("RPC_" + simpleName + "_Consumer");
        } else {
            key = "RPC_" + simpleName + "_" + invocation.getMethodName() + "_Provider";
            QMonitor.recordOne("RPC_Provider_total");
            QMonitor.recordOne("RPC_" + simpleName + "_Provider");
        }
        try {
            return invoker.invoke(invocation);
        } catch (RpcException e) {
            if (e.isTimeout()) {
                QMonitor.recordOne("RPC_total_TimeOut");
                QMonitor.recordOne(key + "_Timeout");
            } else {
                QMonitor.recordOne("RPC_total_Error");
                QMonitor.recordOne(key + "_Error");
            }
            logger.error("dubbo RpcException", e);
            throw e;
        } catch (RuntimeException e) {
            QMonitor.recordOne(key + "_Error");
            throw e;
        }finally {
            long duration = System.currentTimeMillis() - start;
            QMonitor.recordOne(key, duration);
            if (context.isConsumerSide()){
                parseEsRelation(invocation,duration);
            }
        }
    }

    /**
     */
    private void parseEsRelation(Invocation invocation,long duration){
        try {
            String simpleName = invocation.getInvoker().getInterface().getSimpleName();
            if (StringUtils.equalsIgnoreCase(simpleName, "BaseEsOperationService")){
                QMonitor.recordOne("BaseEsOperationService_total",duration);
            }

            Object[] arguments = invocation.getArguments();
            if (arguments!=null && arguments.length > 0){
                Object argument = arguments[0];
                if (argument instanceof RequestParam){
                    monitorEsRequest(invocation,argument,duration);
                }else if (argument instanceof List){
                    List temp=(List)argument;
                    if (temp.size()>0){
                        Object object = temp.get(0);
                        if (object instanceof RequestParam){
                            monitorEsRequest(invocation,object,duration);
                        }
                    }
                }
            }
        }catch (Exception e){
            logger.error("parseEsRelation error",e);
        }
    }

    private void monitorEsRequest(Invocation invocation,Object object,long duration){
        RequestParam requestParam=(RequestParam)object;
        String simpleName = invocation.getInvoker().getInterface().getSimpleName();
        String index = requestParam.getIndex();
        String index_operate = simpleName + "_request_" + index;
        QMonitor.recordOne(index_operate,duration);
        //只区分 query和非query
        String methodName = invocation.getMethodName();
        if (methodName.contains("query")||methodName.contains("scroll")
                ||methodName.contains("count")||methodName.contains("get")){
            QMonitor.recordOne(index_operate+"_query",duration);
        }else {
            QMonitor.recordOne(index_operate+"_not_query",duration);
        }
    }
}
